﻿/*===================================================
* CLR版本  : 4.0.30319.42000 
* 类名称   : Entity
* 文 件 名 : Entity 
* 类描述   :
* 创建人   : oream
* 创建时间 : 2018/3/5 0:43:41
* 修改人   : 
* 修改时间 :
* 版本： @version 1.0
=====================================================*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;

namespace Model
{
  public class Entity : Component
  {

    private readonly Dictionary<Type, Component> dicCmoponentDir;

    protected Entity()
    {
      this.Id = IDGenerater.GenerateId();
      this.dicCmoponentDir = new Dictionary<Type, Component>();
    }

    protected Entity(long id)
    {
      this.Id = id;
      this.dicCmoponentDir = new Dictionary<Type, Component>();
    }

    public override void Dispose()
    {
      if (this.Id == 0) return;

      base.Dispose();

      foreach (var item in dicCmoponentDir.Values)
      {
        try
        {
          item.Dispose();
        }
        catch (Exception e)
        {
          Debug.LogError(e.ToString());
        }
      }
      this.dicCmoponentDir.Clear();
    }


    #region AddComponent
    public void AddComponent<T>() where T : Component, new()
    {
      T tmp = ComponentFactory.Create<T>(this);
      if (dicCmoponentDir.ContainsKey(tmp.GetType()))
      {
        throw new Exception($"AddComponent Error, component existing ! id :{tmp.Id} ,component : {tmp.GetType().Name}");
      }
      this.dicCmoponentDir.Add(tmp.GetType(), tmp);
    }

    public void AddComponent<T1, T2>(T2 t2) where T1 : Component, new()
    {
      T1 tmp = ComponentFactory.Create<T1, T2>(this, t2);
      if (dicCmoponentDir.ContainsKey(tmp.GetType()))
      {
        throw new Exception($"AddComponent Error, component existing ! id :{tmp.Id} ,component : {tmp.GetType().Name}");
      }
      this.dicCmoponentDir.Add(tmp.GetType(), tmp);
    }

    public void AddComponent<T1, T2, T3>(T2 t2, T3 t3) where T1 : Component, new()
    {
      T1 tmp = ComponentFactory.Create<T1, T2, T3>(this, t2, t3);
      if (dicCmoponentDir.ContainsKey(tmp.GetType()))
      {
        throw new Exception($"AddComponent Error, component existing ! id :{tmp.Id} ,component : {tmp.GetType().Name}");
      }
      this.dicCmoponentDir.Add(tmp.GetType(), tmp);
    }

    public void AddComponent<T1, T2, T3, T4>(T2 t2, T3 t3, T4 t4) where T1 : Component, new()
    {
      T1 tmp = ComponentFactory.Create<T1, T2, T3, T4>(this, t2, t3, t4);
      if (dicCmoponentDir.ContainsKey(tmp.GetType()))
      {
        throw new Exception($"AddComponent Error, component existing ! id :{tmp.Id} ,component : {tmp.GetType().Name}");
      }
      this.dicCmoponentDir.Add(tmp.GetType(), tmp);
    }
    #endregion

    public void RemoveComponent<T>()
    {
      Component component;
      if (this.dicCmoponentDir.TryGetValue(typeof(T), out component))
      {
        component.Dispose();
        this.dicCmoponentDir.Remove(component.GetType());
      }
    }

    public void RemoveComponent(Type type)
    {
      Component component;
      if (this.dicCmoponentDir.TryGetValue(type, out component))
      {
        component.Dispose();
        this.dicCmoponentDir.Remove(type);
      }
    }

    public T GetComponent<T>() where T : Component
    {
      Component component;
      if (!this.dicCmoponentDir.TryGetValue(typeof(T), out component))
      {
        return null;
      }
      return (T)component;
    }

    public Component[] GetComponents()
    {
      return this.dicCmoponentDir.Values.ToArray();
    }
  }
}
